package com.vegetable.modules.service.finance.impl;

import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.vegetable.modules.entity.finance.po.ProjectProfitQueryPO;
import com.vegetable.modules.entity.finance.vo.ExpenseDetailVO;
import com.vegetable.modules.entity.finance.vo.ProjectProfitSummaryVO;
import com.vegetable.modules.entity.finance.vo.FinanceTrendVO;
import com.vegetable.modules.entity.finance.vo.ExpenseRatioVO;
import com.vegetable.modules.entity.finance.vo.CommoditySalesVO;
import com.vegetable.modules.entity.finance.vo.PackPurchaseVO;
import com.vegetable.modules.entity.finance.vo.CustomerSalesVO;
import com.vegetable.modules.entity.finance.vo.PackLossPageVO;
import com.vegetable.modules.entity.finance.vo.PackLossVO;
import com.vegetable.modules.entity.finance.vo.CommoditySalesPageVO;
import com.vegetable.modules.entity.finance.vo.PackPurchasePageVO;
import com.vegetable.modules.entity.finance.vo.CustomerSalesPageVO;
import com.vegetable.modules.mapper.finance.ProjectProfitMapper;
import com.vegetable.modules.service.finance.ProjectProfitService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 项目盈利情况统计服务实现类
 */
@Service
public class ProjectProfitServiceImpl implements ProjectProfitService {

    @Autowired
    private ProjectProfitMapper projectProfitMapper;

    @Override
    public ProjectProfitSummaryVO getProjectProfitSummary(ProjectProfitQueryPO po) {
        // 设置默认时间范围为最近30天
        if (po.getStartDate() == null) {
            po.setStartDate(DateUtil.offsetDay(new Date(), -30));
        }
        if (po.getEndDate() == null) {
            po.setEndDate(new Date());
        }
        
        // 设置默认regionId为1（如果未提供）
        if (po.getRegionId() == null) {
            po.setRegionId(1);
        }

        ProjectProfitSummaryVO summary = new ProjectProfitSummaryVO();
        
        // 获取销售收入
        BigDecimal totalSales = projectProfitMapper.getTotalSales(po.getRegionId(), po.getStartDate(), po.getEndDate());
        summary.setTotalSales(totalSales == null ? BigDecimal.ZERO : totalSales);
        
        // 获取销售成本
        BigDecimal totalCost = projectProfitMapper.getTotalCost(po.getRegionId(), po.getStartDate(), po.getEndDate());
        summary.setTotalCost(totalCost == null ? BigDecimal.ZERO : totalCost);
        
        // 计算利润
        summary.setTotalProfit(summary.getTotalSales().subtract(summary.getTotalCost()));
        
        // 获取各项费用支出
        BigDecimal reimbursement = projectProfitMapper.getTotalReimbursement(po.getRegionId(), po.getStartDate(), po.getEndDate());
        summary.setTotalReimbursement(reimbursement == null ? BigDecimal.ZERO : reimbursement);
        
        BigDecimal purchaseCost = projectProfitMapper.getTotalPurchaseCost(po.getRegionId(), po.getStartDate(), po.getEndDate());
        summary.setTotalPurchaseCost(purchaseCost == null ? BigDecimal.ZERO : purchaseCost);
        
        BigDecimal agentCost = projectProfitMapper.getTotalAgentCost(po.getRegionId(), po.getStartDate(), po.getEndDate());
        summary.setTotalAgentCost(agentCost == null ? BigDecimal.ZERO : agentCost);
        
        BigDecimal packCost = projectProfitMapper.getTotalPackCost(po.getRegionId(), po.getStartDate(), po.getEndDate());
        summary.setTotalPackCost(packCost == null ? BigDecimal.ZERO : packCost);
        
        // 计算总支出
        BigDecimal totalExpense = summary.getTotalReimbursement()
                .add(summary.getTotalPurchaseCost())
                .add(summary.getTotalAgentCost())
                .add(summary.getTotalPackCost());
        summary.setTotalExpense(totalExpense);
        
        // 计算净利润
        summary.setNetProfit(summary.getTotalProfit().subtract(totalExpense));
        
        // 计算各项支出占比
        if (totalExpense.compareTo(BigDecimal.ZERO) > 0) {
            summary.setReimbursementRatio(reimbursement.multiply(BigDecimal.valueOf(100)).divide(totalExpense, 2, BigDecimal.ROUND_HALF_UP));
            summary.setPurchaseRatio(purchaseCost.multiply(BigDecimal.valueOf(100)).divide(totalExpense, 2, BigDecimal.ROUND_HALF_UP));
            summary.setAgentRatio(agentCost.multiply(BigDecimal.valueOf(100)).divide(totalExpense, 2, BigDecimal.ROUND_HALF_UP));
            summary.setPackRatio(packCost.multiply(BigDecimal.valueOf(100)).divide(totalExpense, 2, BigDecimal.ROUND_HALF_UP));
        }
        
        // 获取项目回款总额
        BigDecimal totalCollection = projectProfitMapper.getTotalCollection(po.getRegionId(), po.getStartDate(), po.getEndDate());
        summary.setTotalCollection(totalCollection == null ? BigDecimal.ZERO : totalCollection);
        
        // 计算回款率
        if (summary.getTotalSales().compareTo(BigDecimal.ZERO) > 0) {
            summary.setCollectionRate(summary.getTotalCollection().multiply(BigDecimal.valueOf(100)).divide(summary.getTotalSales(), 2, BigDecimal.ROUND_HALF_UP));
        }
        
        return summary;
    }

    @Override
    public IPage<ExpenseDetailVO> getExpenseDetails(ProjectProfitQueryPO po) {
        // 设置默认时间范围为最近30天
        if (po.getStartDate() == null) {
            po.setStartDate(DateUtil.offsetDay(new Date(), -30));
        }
        if (po.getEndDate() == null) {
            po.setEndDate(new Date());
        }
        
        // 设置默认regionId为1（如果未提供）
        if (po.getRegionId() == null) {
            po.setRegionId(1);
        }
        
        // 设置分页参数
        if (po.getPage() == null || po.getPage() <= 0) {
            po.setPage(1L);
        }
        if (po.getLimit() == null || po.getLimit() <= 0) {
            po.setLimit(10L);
        }
        
        // 计算OFFSET
        long offset = (po.getPage() - 1) * po.getLimit();
        
        // 创建分页对象
        IPage<ExpenseDetailVO> page = new Page<>(po.getPage(), po.getLimit());
        
        // 如果指定了费用类型，直接查询该类型的明细
        if (po.getExpenseType() != null && !po.getExpenseType().isEmpty()) {
            switch (po.getExpenseType()) {
                case "费用报销":
                    page.setRecords(projectProfitMapper.getReimbursementDetails(po.getRegionId(), po.getStartDate(), po.getEndDate(), offset, po.getLimit()));
                    page.setTotal(projectProfitMapper.getReimbursementDetailsCount(po.getRegionId(), po.getStartDate(), po.getEndDate()));
                    break;
                case "采购费用":
                    page.setRecords(projectProfitMapper.getPurchaseDetails(po.getRegionId(), po.getStartDate(), po.getEndDate(), offset, po.getLimit()));
                    page.setTotal(projectProfitMapper.getPurchaseDetailsCount(po.getRegionId(), po.getStartDate(), po.getEndDate()));
                    break;
                case "代办费用":
                    page.setRecords(projectProfitMapper.getAgentDetails(po.getRegionId(), po.getStartDate(), po.getEndDate(), offset, po.getLimit()));
                    page.setTotal(projectProfitMapper.getAgentDetailsCount(po.getRegionId(), po.getStartDate(), po.getEndDate()));
                    break;
                case "加工费用":
                    page.setRecords(projectProfitMapper.getPackDetails(po.getRegionId(), po.getStartDate(), po.getEndDate(), offset, po.getLimit()));
                    page.setTotal(projectProfitMapper.getPackDetailsCount(po.getRegionId(), po.getStartDate(), po.getEndDate()));
                    break;
                default:
                    page.setRecords(new ArrayList<>());
                    page.setTotal(0L);
                    break;
            }
        } else {
            // 如果没有指定费用类型，查询所有类型的明细并合并结果
            List<ExpenseDetailVO> allDetails = new ArrayList<>();
            
            // 获取各类型明细（获取足够多的数据用于排序和分页）
            List<ExpenseDetailVO> reimbursementDetails = projectProfitMapper.getReimbursementDetails(po.getRegionId(), po.getStartDate(), po.getEndDate(), 0L, po.getPage() * po.getLimit());
            List<ExpenseDetailVO> purchaseDetails = projectProfitMapper.getPurchaseDetails(po.getRegionId(), po.getStartDate(), po.getEndDate(), 0L, po.getPage() * po.getLimit());
            List<ExpenseDetailVO> agentDetails = projectProfitMapper.getAgentDetails(po.getRegionId(), po.getStartDate(), po.getEndDate(), 0L, po.getPage() * po.getLimit());
            List<ExpenseDetailVO> packDetails = projectProfitMapper.getPackDetails(po.getRegionId(), po.getStartDate(), po.getEndDate(), 0L, po.getPage() * po.getLimit());
            
            // 合并所有明细
            allDetails.addAll(reimbursementDetails);
            allDetails.addAll(purchaseDetails);
            allDetails.addAll(agentDetails);
            allDetails.addAll(packDetails);
            
            // 按日期排序
            allDetails.sort((a, b) -> b.getExpenseDate().compareTo(a.getExpenseDate()));
            
            // 获取总数
            long total = 0;
            total += projectProfitMapper.getReimbursementDetailsCount(po.getRegionId(), po.getStartDate(), po.getEndDate());
            total += projectProfitMapper.getPurchaseDetailsCount(po.getRegionId(), po.getStartDate(), po.getEndDate());
            total += projectProfitMapper.getAgentDetailsCount(po.getRegionId(), po.getStartDate(), po.getEndDate());
            total += projectProfitMapper.getPackDetailsCount(po.getRegionId(), po.getStartDate(), po.getEndDate());
            
            // 分页处理
            int fromIndex = (int) Math.min(offset, allDetails.size());
            int toIndex = (int) Math.min(fromIndex + po.getLimit(), allDetails.size());
            
            // 设置分页结果
            page.setRecords(allDetails.subList(fromIndex, toIndex));
            page.setTotal(total);
        }
        
        return page;
    }

    @Override
    public FinanceTrendVO getFinanceTrend(ProjectProfitQueryPO po) {
        // 设置默认时间范围为最近30天
        if (po.getStartDate() == null) {
            po.setStartDate(DateUtil.offsetDay(new Date(), -30));
        }
        if (po.getEndDate() == null) {
            po.setEndDate(new Date());
        }
        
        // 设置默认regionId为1（如果未提供）
        if (po.getRegionId() == null) {
            po.setRegionId(1);
        }
        
        FinanceTrendVO trend = new FinanceTrendVO();
        trend.setIncomeTrend(projectProfitMapper.getIncomeTrend(po.getRegionId(), po.getStartDate(), po.getEndDate(), po.getType()));
        trend.setExpenseTrend(projectProfitMapper.getExpenseTrend(po.getRegionId(), po.getStartDate(), po.getEndDate(), po.getType()));
        return trend;
    }

    @Override
    public ExpenseRatioVO getExpenseRatio(ProjectProfitQueryPO po) {
        // 设置默认时间范围为最近30天
        if (po.getStartDate() == null) {
            po.setStartDate(DateUtil.offsetDay(new Date(), -30));
        }
        if (po.getEndDate() == null) {
            po.setEndDate(new Date());
        }
        
        // 设置默认regionId为1（如果未提供）
        if (po.getRegionId() == null) {
            po.setRegionId(1);
        }
        
        ExpenseRatioVO ratio = new ExpenseRatioVO();
        ratio.setReimbursementRatio(java.util.Arrays.asList(projectProfitMapper.getReimbursementRatio(po.getRegionId(), po.getStartDate(), po.getEndDate())));
        ratio.setPurchaseRatio(java.util.Arrays.asList(projectProfitMapper.getPurchaseRatio(po.getRegionId(), po.getStartDate(), po.getEndDate())));
        ratio.setAgentRatio(java.util.Arrays.asList(projectProfitMapper.getAgentRatio(po.getRegionId(), po.getStartDate(), po.getEndDate())));
        ratio.setPackRatio(java.util.Arrays.asList(projectProfitMapper.getPackRatio(po.getRegionId(), po.getStartDate(), po.getEndDate())));
        return ratio;
    }
    
    @Override
    public IPage<CommoditySalesVO> getSalesByCommodity(ProjectProfitQueryPO po) {
        // 设置默认时间范围为最近30天
        if (po.getStartDate() == null) {
            po.setStartDate(DateUtil.offsetDay(new Date(), -30));
        }
        if (po.getEndDate() == null) {
            po.setEndDate(new Date());
        }
        
        // 设置默认regionId为1（如果未提供）
        if (po.getRegionId() == null) {
            po.setRegionId(1);
        }
        
        // 计算OFFSET
        long offset = (po.getPage() - 1) * po.getLimit();
        
        // 创建分页对象
        IPage<CommoditySalesVO> page = new Page<>(po.getPage(), po.getLimit());
        
        // 获取数据
        page.setRecords(projectProfitMapper.getSalesByCommodity(po.getRegionId(), po.getStartDate(), po.getEndDate(), po.getCommodityName(), offset, po.getLimit()));
        page.setTotal(projectProfitMapper.getSalesByCommodityCount(po.getRegionId(), po.getStartDate(), po.getEndDate(), po.getCommodityName()));
        
        return page;
    }
    
    @Override
    public CommoditySalesPageVO getSalesByCommodityWithTotal(ProjectProfitQueryPO po) {
        // 设置默认时间范围为最近30天
        if (po.getStartDate() == null) {
            po.setStartDate(DateUtil.offsetDay(new Date(), -30));
        }
        if (po.getEndDate() == null) {
            po.setEndDate(new Date());
        }
        
        // 设置默认regionId为1（如果未提供）
        if (po.getRegionId() == null) {
            po.setRegionId(1);
        }
        
        // 计算OFFSET
        long offset = (po.getPage() - 1) * po.getLimit();
        
        // 创建分页对象
        IPage<CommoditySalesVO> page = new Page<>(po.getPage(), po.getLimit());
        
        // 获取分页数据
        page.setRecords(projectProfitMapper.getSalesByCommodity(po.getRegionId(), po.getStartDate(), po.getEndDate(), po.getCommodityName(), offset, po.getLimit()));
        page.setTotal(projectProfitMapper.getSalesByCommodityCount(po.getRegionId(), po.getStartDate(), po.getEndDate(), po.getCommodityName()));
        
        // 获取总统计数据
        CommoditySalesVO totalStats = projectProfitMapper.getTotalSalesByCommodity(po.getRegionId(), po.getStartDate(), po.getEndDate(), po.getCommodityName());
        
        // 创建返回对象
        CommoditySalesPageVO result = new CommoditySalesPageVO();
        result.setPageData(page);
        result.setTotalSalesAmount(totalStats.getTotalSalesAmount() != null ? totalStats.getTotalSalesAmount() : BigDecimal.ZERO);
        result.setTotalWeight(totalStats.getTotalWeight() != null ? totalStats.getTotalWeight() : BigDecimal.ZERO);
        result.setTotalQuantity(totalStats.getTotalQuantity() != null ? totalStats.getTotalQuantity() : BigDecimal.ZERO);
        result.setOrderCount(totalStats.getOrderCount() != null ? totalStats.getOrderCount() : 0);
        
        return result;
    }
    
    @Override
    public IPage<PackPurchaseVO> getPackPurchaseDetails(ProjectProfitQueryPO po) {
        // 设置默认时间范围为最近30天
        if (po.getStartDate() == null) {
            po.setStartDate(DateUtil.offsetDay(new Date(), -30));
        }
        if (po.getEndDate() == null) {
            po.setEndDate(new Date());
        }
        
        // 设置默认regionId为1（如果未提供）
        if (po.getRegionId() == null) {
            po.setRegionId(1);
        }
        
        // 计算OFFSET
        long offset = (po.getPage() - 1) * po.getLimit();
        
        // 创建分页对象
        IPage<PackPurchaseVO> page = new Page<>(po.getPage(), po.getLimit());
        
        // 获取数据
        page.setRecords(projectProfitMapper.getPackPurchaseDetails(po.getRegionId(), po.getStartDate(), po.getEndDate(), po.getCommodityName(), po.getSupplierName(), offset, po.getLimit()));
        page.setTotal(projectProfitMapper.getPackPurchaseDetailsCount(po.getRegionId(), po.getStartDate(), po.getEndDate(), po.getCommodityName(), po.getSupplierName()));
        
        return page;
    }
    
    @Override
    public PackPurchasePageVO getPackPurchaseDetailsWithTotal(ProjectProfitQueryPO po) {
        // 设置默认时间范围为最近30天
        if (po.getStartDate() == null) {
            po.setStartDate(DateUtil.offsetDay(new Date(), -30));
        }
        if (po.getEndDate() == null) {
            po.setEndDate(new Date());
        }
        
        // 设置默认regionId为1（如果未提供）
        if (po.getRegionId() == null) {
            po.setRegionId(1);
        }
        
        // 计算OFFSET
        long offset = (po.getPage() - 1) * po.getLimit();
        
        // 创建分页对象
        IPage<PackPurchaseVO> page = new Page<>(po.getPage(), po.getLimit());
        
        // 获取分页数据
        page.setRecords(projectProfitMapper.getPackPurchaseDetails(po.getRegionId(), po.getStartDate(), po.getEndDate(), po.getCommodityName(), po.getSupplierName(), offset, po.getLimit()));
        page.setTotal(projectProfitMapper.getPackPurchaseDetailsCount(po.getRegionId(), po.getStartDate(), po.getEndDate(), po.getCommodityName(), po.getSupplierName()));
        
        // 获取总统计数据
        PackPurchaseVO totalStats = projectProfitMapper.getTotalPackPurchase(po.getRegionId(), po.getStartDate(), po.getEndDate(), po.getCommodityName(), po.getSupplierName());
        
        // 创建返回对象
        PackPurchasePageVO result = new PackPurchasePageVO();
        result.setPageData(page);
        result.setPurchaseAmount(totalStats.getPurchaseAmount() != null ? totalStats.getPurchaseAmount() : BigDecimal.ZERO);
        result.setWeight(totalStats.getWeight() != null ? totalStats.getWeight() : BigDecimal.ZERO);
        result.setQuantity(totalStats.getQuantity() != null ? totalStats.getQuantity() : BigDecimal.ZERO);
        
        return result;
    }
    
    @Override
    public IPage<CustomerSalesVO> getSalesByCustomer(ProjectProfitQueryPO po) {
        // 设置默认时间范围为最近30天
        if (po.getStartDate() == null) {
            po.setStartDate(DateUtil.offsetDay(new Date(), -30));
        }
        if (po.getEndDate() == null) {
            po.setEndDate(new Date());
        }
        
        // 设置默认regionId为1（如果未提供）
        if (po.getRegionId() == null) {
            po.setRegionId(1);
        }
        
        // 计算OFFSET
        long offset = (po.getPage() - 1) * po.getLimit();
        
        // 创建分页对象
        IPage<CustomerSalesVO> page = new Page<>(po.getPage(), po.getLimit());
        
        // 获取数据
        page.setRecords(projectProfitMapper.getSalesByCustomer(po.getRegionId(), po.getStartDate(), po.getEndDate(), po.getCustomerName(), offset, po.getLimit()));
        page.setTotal(projectProfitMapper.getSalesByCustomerCount(po.getRegionId(), po.getStartDate(), po.getEndDate(), po.getCustomerName()));
        
        return page;
    }
    
    @Override
    public CustomerSalesPageVO getSalesByCustomerWithTotal(ProjectProfitQueryPO po) {
        // 设置默认时间范围为最近30天
        if (po.getStartDate() == null) {
            po.setStartDate(DateUtil.offsetDay(new Date(), -30));
        }
        if (po.getEndDate() == null) {
            po.setEndDate(new Date());
        }
        
        // 设置默认regionId为1（如果未提供）
        if (po.getRegionId() == null) {
            po.setRegionId(1);
        }
        
        // 计算OFFSET
        long offset = (po.getPage() - 1) * po.getLimit();
        
        // 创建分页对象
        IPage<CustomerSalesVO> page = new Page<>(po.getPage(), po.getLimit());
        
        // 获取分页数据
        page.setRecords(projectProfitMapper.getSalesByCustomer(po.getRegionId(), po.getStartDate(), po.getEndDate(), po.getCustomerName(), offset, po.getLimit()));
        page.setTotal(projectProfitMapper.getSalesByCustomerCount(po.getRegionId(), po.getStartDate(), po.getEndDate(), po.getCustomerName()));
        
        // 获取总统计数据
        CustomerSalesVO totalStats = projectProfitMapper.getTotalSalesByCustomer(po.getRegionId(), po.getStartDate(), po.getEndDate(), po.getCustomerName());
        
        // 创建返回对象
        CustomerSalesPageVO result = new CustomerSalesPageVO();
        result.setPageData(page);
        result.setTotalSalesAmount(totalStats.getTotalSalesAmount() != null ? totalStats.getTotalSalesAmount() : BigDecimal.ZERO);
        result.setReceivedAmount(totalStats.getReceivedAmount() != null ? totalStats.getReceivedAmount() : BigDecimal.ZERO);
        result.setUnreceivedAmount(totalStats.getUnreceivedAmount() != null ? totalStats.getUnreceivedAmount() : BigDecimal.ZERO);
        result.setCollectionRate(totalStats.getCollectionRate() != null ? totalStats.getCollectionRate() : BigDecimal.ZERO);
        result.setOrderCount(totalStats.getOrderCount() != null ? totalStats.getOrderCount() : 0);
        
        return result;
    }
    
    @Override
    public PackLossPageVO getPackLossDetails(ProjectProfitQueryPO po) {
        // 设置默认时间范围为最近30天
        if (po.getStartDate() == null) {
            po.setStartDate(DateUtil.offsetDay(new Date(), -30));
        }
        if (po.getEndDate() == null) {
            po.setEndDate(new Date());
        }
        
        // 设置默认regionId为1（如果未提供）
        if (po.getRegionId() == null) {
            po.setRegionId(1);
        }
        
        // 设置分页参数
        if (po.getPage() == null || po.getPage() <= 0) {
            po.setPage(1L);
        }
        if (po.getLimit() == null || po.getLimit() <= 0) {
            po.setLimit(10L);
        }
        
        // 计算OFFSET
        long offset = (po.getPage() - 1) * po.getLimit();
        
        // 创建分页对象
        IPage<PackLossVO> page = new Page<>(po.getPage(), po.getLimit());
        
        // 获取数据
        page.setRecords(projectProfitMapper.getPackLossDetails(po.getRegionId(), po.getStartDate(), po.getEndDate(), po.getCommodityName(), offset, po.getLimit()));
        page.setTotal(projectProfitMapper.getPackLossDetailsCount(po.getRegionId(), po.getStartDate(), po.getEndDate(), po.getCommodityName()));
        
        // 获取总损耗统计
        PackLossVO totalLoss = projectProfitMapper.getTotalPackLoss(po.getRegionId(), po.getStartDate(), po.getEndDate(), po.getCommodityName());
        
        // 创建返回对象
        PackLossPageVO result = new PackLossPageVO();
        result.setPageData(page);
        result.setTotalLossWeight(totalLoss.getLossWeight() != null ? totalLoss.getLossWeight() : BigDecimal.ZERO);
        result.setTotalLossAmount(totalLoss.getLossAmount() != null ? totalLoss.getLossAmount() : BigDecimal.ZERO);
        
        return result;
    }
}